/**
 * 生成随机颜色
 * @returns
 */
export const randomColor = () => {
  // 生成一个0-16777215之间的随机数，然后转换为16进制，并补齐6位
  return `#${Math.floor(Math.random() * 0xffffff)
    .toString(16)
    .padEnd(6, '0')}`
}

/**
 * 判断是否 十六进制颜色值.
 * 输入形式可为 #fff000 #f00
 *
 * @param   String  color   十六进制颜色值
 * @return  Boolean
 */
export const isHexColor = (color: string) => {
  const reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-f]{6})$/
  return reg.test(color)
}

/**
 * RGB 颜色值转换为 十六进制颜色值.
 * r, g, 和 b 需要在 [0, 255] 范围内
 *
 * @return  String          类似#ff00ff
 * @param r
 * @param g
 * @param b
 */
export const rgbToHex = (r: number, g: number, b: number) => {
  // tslint:disable-next-line:no-bitwise
  const hex = ((r << 16) | (g << 8) | b).toString(16)
  return '#' + new Array(Math.abs(hex.length - 7)).join('0') + hex
}

/**
 * 将十六进制颜色转换为RGB颜色
 * @param hex 颜色值
 * @param opacity 透明度
 * @returns
 */
export const hexToRGB = (hex: string, opacity?: number) => {
  // 将十六进制颜色转换为小写
  let sHex = hex.toLowerCase()
  // 判断是否为十六进制颜色
  if (isHexColor(hex)) {
    // 如果十六进制颜色长度为4，则将其转换为6位
    if (sHex.length === 4) {
      let sColorNew = '#'
      for (let i = 1; i < 4; i += 1) {
        sColorNew += sHex.slice(i, i + 1).concat(sHex.slice(i, i + 1))
      }
      sHex = sColorNew
    }
    // 将十六进制颜色转换为RGB颜色
    const sColorChange: number[] = []
    for (let i = 1; i < 7; i += 2) {
      sColorChange.push(parseInt('0x' + sHex.slice(i, i + 2)))
    }
    // 如果有透明度参数，则返回RGBA颜色，否则返回RGB颜色
    return opacity
      ? 'RGBA(' + sColorChange.join(',') + ',' + opacity + ')'
      : 'RGB(' + sColorChange.join(',') + ')'
  }
  // 如果不是十六进制颜色，则返回原颜色
  return sHex
}

export const colorIsDark = (color: string) => {
  if (!isHexColor(color)) return
  const [r, g, b] = hexToRGB(color)
    .replace(/(?:\(|\)|rgb|RGB)*/g, '')
    .split(',')
    .map((item) => Number(item))
  return r * 0.299 + g * 0.578 + b * 0.114 < 192
}

/**
 * 将颜色变暗
 * @param color 颜色值
 * @param amount
 * @returns
 */
export const darken = (color: string, amount: number) => {
  // 如果颜色字符串中包含#，则去掉#号
  color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color
  // 计算变暗的数值
  amount = Math.trunc((255 * amount) / 100)
  // 返回变暗后的颜色字符串
  return `#${subtractLight(color.substring(0, 2), amount)}${subtractLight(
    color.substring(2, 4),
    amount
  )}${subtractLight(color.substring(4, 6), amount)}`
}

/**
 * 将颜色变亮
 * @param color 颜色值
 * @param amount 增加的数量
 * @returns
 */
export const lighten = (color: string, amount: number) => {
  // 如果颜色字符串中包含#，则去掉#号
  color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color
  // 计算变亮的程度
  amount = Math.trunc((255 * amount) / 100)
  // 返回变亮后的颜色字符串
  return `#${addLight(color.substring(0, 2), amount)}${addLight(
    color.substring(2, 4),
    amount
  )}${addLight(color.substring(4, 6), amount)}`
}

/**
 * 用于将颜色值增加一定数量
 * @param color 颜色值
 * @param amount 增加的数量
 * @returns
 */
const addLight = (color: string, amount: number) => {
  // 将颜色值转换为16进制数，并加上增加的数量
  const cc = parseInt(color, 16) + amount
  // 如果增加后的值大于255，则将其设置为255
  const c = cc > 255 ? 255 : cc
  // 将增加后的值转换为16进制字符串，如果长度大于1，则直接返回，否则在前面加一个0
  return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`
}

/**
 * 计算颜色的亮度
 * @param r 红
 * @param g
 * @param b
 * @returns
 */
const luminanace = (r: number, g: number, b: number) => {
  // 将rgb值除以255，得到0-1之间的值
  const a = [r, g, b].map((v) => {
    v /= 255
    // 如果值小于等于0.03928，则除以12.92，否则将值加0.055后除以1.055，再开2.4次方
    return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4)
  })
  // 返回亮度值，根据人眼对颜色的敏感度，将r、g、b的值分别乘以0.2126、0.7152、0.0722，然后相加
  return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722
}

/**
 * 计算两个RGB颜色之间的对比度
 * @param rgb1 rgb颜色1
 * @param rgb2 rgb颜色2
 * @returns
 */
const contrast = (rgb1: string[], rgb2: number[]) => {
  return (
    (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) /
    (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05)
  )
}

/**
 * 根据背景颜色匹配最佳的文字颜色（黑色或白色）
 * @param hexColor 传入的十六进制颜色
 * @returns
 */
export const calculateBestTextColor = (hexColor: string) => {
  // 将传入的十六进制颜色转换为RGB颜色
  const rgbColor = hexToRGB(hexColor.substring(1))
  // 计算RGB颜色与黑色之间的对比度
  const contrastWithBlack = contrast(rgbColor.split(','), [0, 0, 0])

  // 如果对比度大于等于12，则返回黑色，否则返回白色
  return contrastWithBlack >= 12 ? '#000000' : '#FFFFFF'
}

/**
 * 将颜色值减去指定数量
 * @param color 颜色值
 * @param amount 指定数量
 * @returns Hex颜色
 */
const subtractLight = (color: string, amount: number) => {
  // 将颜色值转换为十进制数，并减去指定数量
  const cc = parseInt(color, 16) - amount
  // 如果减去后的值小于0，则将其设置为0
  const c = cc < 0 ? 0 : cc
  // 将减去后的值转换为十六进制数，并返回
  return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`
}

/** 预设颜色 */
export const PREDEFINE_COLORS = [
  '#ff4500',
  '#ff8c00',
  '#ffd700',
  '#90ee90',
  '#00ced1',
  '#1e90ff',
  '#c71585',
  '#409EFF',
  '#909399',
  '#C0C4CC',
  '#b7390b',
  '#ff7800',
  '#fad400',
  '#5b8c5f',
  '#00babd',
  '#1f73c3',
  '#711f57'
]
